<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <meta property="og:title" content="Haskell 趣學指南" />
        <meta property="og:type" content="website" />
        <meta property="og:url" content="http://learnyouahaskell-zh-tw.csie.org" />
        <meta property="og:image" content="http://learnyouahaskell-zh-tw.csie.org/img/bird.png" />

        <style type="text/css">
            @import url(../css/style.css);
            @import url(../css/feedback.css);
        </style>
        <script type="text/javascript" src="../js/jquery.js"></script>
        <script type="text/javascript" src="../js/jquery.chili-2.2.js"></script>
        <script type="text/javascript" src="../js/script.js"></script>
        <script type="text/javascript" src="../js/html2canvas.js"></script>
        <script type="text/javascript" src="../js/jsfeedback.js"></script>
        <script type="text/javascript">
             ChiliBook.recipeFolder = "../js/chili/";  
             ChiliBook.automaticSelector = "pre";
        </script>
        <script type="text/javascript">
            $(function(){
                $('#feedback').click(function(){
                    $('body').feedback();
                })
            });
        </script>
        <script defer type="text/javascript">
            var _gaq = _gaq || [];
            _gaq.push(['_setAccount', 'UA-32830659-1']);
            _gaq.push(['_trackPageview']);

            (function() {
                var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
                ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
                    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
            })();
        </script>
        <title>來看看幾種 Monad</title>
    </head>
    <body>
        <div id="header">
        </div>

        <div id="main">
            <ul class="nav">
                <li class="left">  <img src="../img/prv.png" alt="prev" /><a href="functors-applicative-functors-and-monoids.html">Functors, Applicative Functors 與 Monoids</a></li>
                <li class="center"><a href="chapters.html">目录</a></li>
                <li class="right"> <a href="for-a-few-monads-more.html">再來看看更多 Monad</a><img src="../img/nxt.png" alt="next" /></li>
            </ul>
            <a name="來看看幾種_Monad"></a><h1>來看看幾種 Monad</h1>


<p>當我們第一次談到 Functor 的時候，我們了解到他是一個抽象概念，代表是一種可以被 map over 的值。然後我們再將其概念提升到 Applicative Functor，他代表一種帶有 context 的型態，我們可以用函數操作他而且同時還保有他的 context。</p>

<p>在這一章，我們會學到 Monad，基本上他是一種加強版的 Applicative Functor，正如 Applicative Functor 是 Functor 的加強版一樣。</p>
<img src="../img/smugpig.png" alt="" style="float:right" class="floatright" />
<p>我們介紹到 Functor 是因為我們觀察到有許多型態都可以被 function 給 map over，了解到這個目的，便抽象化了 <code>Functor</code> 這個 typeclass 出來。但這讓我們想問：如果給定一個 <code>a -&gt; b</code> 的函數以及 <code>f a</code> 的型態，我們要如何將函數 map over 這個型態而得到 <code>f b</code>？我們知道要如何 map over <code>Maybe a</code>，<code>[a]</code> 以及 <code>IO a</code>。我們甚至還知道如何用 <code>a -&gt; b</code> map over <code>r -&gt; a</code>，並且會得到 <code>r -&gt; b</code>。要回答這個問題，我們只需要看 <code>fmap</code> 的型態就好了：</p>
<pre class="code">fmap :: (Functor f) =&gt; (a -&gt; b) -&gt; f a -&gt; f b</pre>
<p>然後只要針對 <code>Functor</code> instance 撰寫對應的實作。</p>

<p>之後我們又看到一些可以針對 Functor 改進的地方，例如 <code>a -&gt; b</code> 也被包在一個 Functor value 裡面呢？像是 <code>Just (*3)</code>，我們要如何 apply <code>Just 5</code> 給他？如果我們不要 apply <code>Just 5</code> 而是 <code>Nothing</code> 呢？甚至給定 <code>[(*2),(+4)]</code>，我們要如何 apply 他們到 <code>[1,2,3]</code> 呢？對於此，我們抽象出 <code>Applicative</code> typeclass，這就是我們想要問的問題：</p>
<pre class="code">(&lt;*&gt;) :: (Applicative f) =&gt; f (a -&gt; b) -&gt; f a -&gt; f b</pre>
<p>我們也看到我們可以將一個正常的值包在一個資料型態中。例如說我們可以拿一個 <code>1</code> 然後把他包成 <code>Just 1</code>。或是把他包成 <code>[1]</code>。也可以是一個 I/O action 會產生一個 <code>1</code>。這樣包裝的 function 我們叫他做 <code>pure</code>。</p>

<p>如我們說得，一個 applicative value 可以被看作一個有附加 context 的值。例如說，<code>'a'</code> 只是一個普通的字元，但 <code>Just 'a'</code> 是一個附加了 context 的字元。他不是 <code>Char</code> 而是 <code>Maybe Char</code>，這型態告訴我們這個值可能是一個字元，也可能什麼都沒有。</p>

<p>來看看 <code>Applicative</code> typeclass 怎樣讓我們用普通的 function 操作他們，同時還保有 context：</p>
<pre class="code">ghci&gt; (*) &lt;$&gt; Just 2 &lt;*&gt; Just 8  
Just 16  
ghci&gt; (++) &lt;$&gt; Just "klingon" &lt;*&gt; Nothing  
Nothing  
ghci&gt; (-) &lt;$&gt; [3,4] &lt;*&gt; [1,2,3]  
[2,1,0,3,2,1]</pre>
<p>所以我們可以視他們為 applicative values，<code>Maybe a</code> 代表可能會失敗的 computation，<code>[a]</code> 代表同時有好多結果的 computation (non-deterministic computation)，而 <code>IO a</code> 代表會有 side-effects 的 computation。</p>

<p>Monad 是一個從 Applicative functors 很自然的一個演進結果。對於他們我們主要考量的點是：如果你有一個具有 context 的值 <code>m a</code>，你能如何把他丟進一個只接受普通值 <code>a</code> 的函數中，並回傳一個具有 context 的值？也就是說，你如何套用一個型態為 <code>a -&gt; m b</code> 的函數至 <code>m a</code>？基本上，我們要求的函數是：</p>
<pre class="code">(&gt;&gt;=) :: (Monad m) =&gt; m a -&gt; (a -&gt; m b) -&gt; m b</pre>
<p>如果我們有一個漂亮的值跟一個函數接受普通的值但回傳漂亮的值，那我們要如何要把漂亮的值丟進函數中？這就是我們使用 Monad 時所要考量的事情。我們不寫成 <code>f a</code> 而寫成 <code>m a</code> 是因為 <code>m</code> 代表的是 <code>Monad</code>，但 monad 不過就是支援 <code>&gt;&gt;=</code> 操作的 applicative functors。<code>&gt;&gt;=</code> 我們稱呼他為 bind。</p>

<p>當我們有一個普通值 <code>a</code> 跟一個普通函數 <code>a -&gt; b</code>，要套用函數是一件很簡單的事。但當你在處理具有 context 的值時，就需要多考慮些東西，要如何把漂亮的值餵進函數中，並如何考慮他們的行為，但你將會了解到他們其實不難。</p>
<a name="動手做做看:_Maybe_Monad"></a><h2>動手做做看: Maybe Monad</h2>

<img src="../img/buddha.png" alt="" style="float:left" class="floatleft" />
<p>現在對於什麼是 Monad 已經有了些模糊的概念，</p>

<p>我們來看看要如何讓這概念更具體一些。</p>

<p>不意外地，<code>Maybe</code> 是一個 Monad，</p>

<p>所以讓我們對於他多探討些，看看是否能跟我們所知的 Monad 概念結合起來。</p>
<blockquote>
<p>到這邊要確定你了解什麼是 Applicatives。如果你知道好幾種 <code>Applicative</code> 的 instance 還有他們代表的意含就更好了，因為 monad 不過就是對 applicative 的概念進行一次升級。</p>
</blockquote>

<p>一個 <code>Maybe a</code> 型態的值代表型態為 <code>a</code> 的值而且具備一個可能造成錯誤的 context。而 <code>Just "dharma"</code> 的值代表他不是一個 <code>"dharma"</code> 的字串就是字串不見時的 <code>Nothing</code>。如果你把字串當作計算的結果，<code>Nothing</code> 就代表計算失敗了。</p>

<p>當我們把 <code>Maybe</code> 視作 functor，我們其實要的是一個 <code>fmap</code> 來把一個函數針對其中的元素做套用。他會對 <code>Just</code> 中的元素進行套用，要不然就是保留 <code>Nothing</code> 的狀態，其代表裡面根本沒有元素。</p>
<pre class="code">ghci&gt; fmap (++"!") (Just "wisdom")  
Just "wisdom!"  
ghci&gt; fmap (++"!") Nothing  
Nothing</pre>
<p>或者視為一個 applicative functor，他也有類似的作用。只是 applicative 也把函數包了起來。<code>Maybe</code> 作為一個 applicative functor，我們能用 <code>&lt;*&gt;</code> 來套用一個存在 <code>Maybe</code> 中的函數至包在另外一個 <code>Maybe</code> 中的值。他們都必須是包在 <code>Just</code> 來代表值存在，要不然其實就是 <code>Nothing</code>。當你在想套用函數到值上面的時候，缺少了函數或是值都會造成錯誤，所以這樣做是很合理的。</p>
<pre class="code">ghci&gt; Just (+3) &lt;*&gt; Just 3  
Just 6  
ghci&gt; Nothing &lt;*&gt; Just "greed"  
Nothing  
ghci&gt; Just ord &lt;*&gt; Nothing  
Nothing</pre>
<p>當我們用 applicative 的方式套用函數至 <code>Maybe</code> 型態的值時，就跟上面描述的差不多。過程中所有值都必須是 <code>Just</code>，要不然結果一定會是 <code>Nothing</code>。</p>
<pre class="code">ghci&gt; max &lt;$&gt; Just 3 &lt;*&gt; Just 6  
Just 6  
ghci&gt; max &lt;$&gt; Just 3 &lt;*&gt; Nothing  
Nothing</pre>
<p>我們來思考一下要怎麼為 <code>Maybe</code> 實作 <code>&gt;&gt;=</code>。正如我們之前提到的，<code>&gt;&gt;=</code> 接受一個 monadic value，以及一個接受普通值的函數，這函數會回傳一個 monadic value。<code>&gt;&gt;=</code> 會幫我們套用這個函數到這個 monadic value。在函數只接受普通值的情況俠，函數是如何作到這件事的呢？要作到這件事，他必須要考慮到 monadic value 的 context。</p>

<p>在這個案例中，<code>&gt;&gt;=</code> 會接受一個 <code>Maybe a</code> 以及一個型態為 <code>a -&gt; Maybe b</code> 的函數。他會套用函數到 <code>Maybe a</code>。要釐清他怎麼作到的，首先我們注意到 <code>Maybe</code> 的 applicative functor 特性。假設我們有一個函數 <code>\x -&gt; Just (x+1)</code>。他接受一個數字，把他加 <code>1</code> 後再包回 <code>Just</code>。</p>
<pre class="code">ghci&gt; (\x -&gt; Just (x+1)) 1  
Just 2  
ghci&gt; (\x -&gt; Just (x+1)) 100  
Just 101</pre>
<p>如果我們餵給函數 <code>1</code>，他會計算成 <code>Just 2</code>。如果我們餵給函數 <code>100</code>，那結果便是 <code>Just 101</code>。但假如我們餵一個 <code>Maybe</code> 的值給函數呢？如果我們把 <code>Maybe</code> 想成一個 applicative functor，那答案便很清楚。如果我們拿到一個 <code>Just</code>，就把包在 <code>Just</code> 裡面的值餵給函數。如果我們拿到一個 <code>Nothing</code>，我們就說結果是 <code>Nothing</code>。</p>

<p>我們呼叫 <code>applyMaybe</code> 而不呼叫 <code>&gt;&gt;=</code>。他接受 <code>Maybe a</code> 跟一個回傳 <code>Maybe b</code> 的函數，並套用函數至 <code>Maybe a</code>。</p>
<pre class="code">applyMaybe :: Maybe a -&gt; (a -&gt; Maybe b) -&gt; Maybe b  
applyMaybe Nothing f  = Nothing  
applyMaybe (Just x) f = f x</pre>
<p>我們套用一個 infix 函數，這樣 <code>Maybe</code> 的值可以寫在左邊且函數是在右邊：</p>
<pre class="code">ghci&gt; Just 3 `applyMaybe` \x -&gt; Just (x+1)  
Just 4  
ghci&gt; Just "smile" `applyMaybe` \x -&gt; Just (x ++ " :")""  
Just "smile :""  
ghci&gt; Nothing `applyMaybe` \x -&gt; Just (x+1)  
Nothing  
ghci&gt; Nothing `applyMaybe` \x -&gt; Just (x ++ " :")")  
Nothing</pre>
<p>在上述的範例中，我們看到在套用 <code>applyMaybe</code> 的時候，函數是套用在 <code>Just</code> 裡面的值。當我們試圖套用到 <code>Nothing</code>，那整個結果便是 <code>Nothing</code>。假如函數回傳 <code>Nothing</code> 呢？</p>
<pre class="code">ghci&gt; Just 3 `applyMaybe` \x -&gt; if x &gt; 2 then Just x else Nothing  
Just 3  
ghci&gt; Just 1 `applyMaybe` \x -&gt; if x &gt; 2 then Just x else Nothing  
Nothing</pre>
<p>這正是我們期待的結果。如果左邊的 monadic value 是 <code>Nothing</code>，那整個結果就是 <code>Nothing</code>。如果右邊的函數是 <code>Nothing</code>，那結果也會是 <code>Nothing</code>。這跟我們之前把 <code>Maybe</code> 當作 applicative 時，過程中有任何一個 <code>Nothing</code> 整個結果就會是 <code>Nothing</code> 一樣。</p>

<p>對於 <code>Maybe</code> 而言，我們已經找到一個方法處理漂亮值的方式。我們作到這件事的同時，也保留了 <code>Maybe</code> 代表可能造成錯誤的計算的意義。</p>

<p>你可能會問，這樣的結果有用嗎？由於 applicative functors 讓我們可以拿一個接受普通值的函數，並讓他可以操作具有 context 的值，這樣看起來 applicative functors 好像比 monad 強。但我們會看到 monad 也能作到，因為他只是 applicative functors 的升級版。他們同時也能作到 applicative functors 不能作到的事情。</p>

<p>稍候我們會再繼續探討 <code>Maybe</code>，但我們先來看看 monad 的 type class。</p>
<a name="Monad_type_class"></a><h2>Monad type class</h2>


<p>正如 functors 有 <code>Functor</code> 這個 type class，而 applicative functors 有一個 <code>Applicative</code> 這個 type class，monad 也有他自己的 type class：<code>Monad</code> 他看起來像這樣：</p>
<pre class="code">class Monad m where  
    return :: a -&gt; m a  

    (&gt;&gt;=) :: m a -&gt; (a -&gt; m b) -&gt; m b  

    (&gt;&gt;) :: m a -&gt; m b -&gt; m b  
    x &gt;&gt; y = x &gt;&gt;= \_ -&gt; y  

    fail :: String -&gt; m a  
    fail msg = error msg</pre><img src="../img/kid.png" alt="" style="float:right" class="floatright" />
<p>我們從第一行開始看。他說 <code>class Monad m where</code>。但我們之前不是提到 monad 是 applicative functors 的加強版嗎？不是應該有一個限制說一個型態必須先是一個 applicative functor 才可能是一個 monad 嗎？像是 <code>class (Applicative m) = &gt; Monad m where</code>。他的確應該要有，但當 Haskell 被創造的早期，人們沒有想到 applicative functor 適合被放進語言中，所以最後沒有這個限制。但的確每個 monad 都是 applicative functor，即使 <code>Monad</code> 並沒有這麼宣告。</p>

<p>在 <code>Monad</code> typeclass 中定義的第一個函數是 <code>return</code>。他其實等價於 <code>pure</code>，只是名字不同罷了。他的型態是 <code>(Monad m) =&gt; a -&gt; m a</code>。他接受一個普通值並把他放進一個最小的 context 中。也就是說他把普通值包進一個 monad 裡面。他跟 <code>Applicative</code> 裡面 <code>pure</code> 函數做的事情一樣，所以說其實我們已經認識了 <code>return</code>。我們已經用過 <code>return</code> 來處理一些 I/O。我們用他來做一些假的 I/O，印出一些值。對於 <code>Maybe</code> 來說他就是接受一個普通值然後包進 <code>Just</code>。</p>
<blockquote>
<p>提醒一下：<code>return</code> 跟其他語言中的 <code>return</code> 是完全不一樣的。他並不是結束一個函數的執行，他只不過是把一個普通值包進一個 context 裡面。</p>
</blockquote>
<img src="../img/tur2.png" alt="" style="float:left" class="floatleft" />
<p>接下來定義的函數是 bind: <code>&gt;&gt;=</code>。他就像是函數套用一樣，只差在他不接受普通值，他是接受一個 monadic value（也就是具有 context 的值）並且把他餵給一個接受普通值的函數，並回傳一個 monadic value。</p>

<p>接下來，我們定義了 <code>&gt;&gt;</code>。我們不會介紹他，因為他有一個事先定義好的實作，基本上我們在實作 <code>Monad</code> typeclass 的時候都不會去理他。</p>

<p>最後一個函數是 <code>fail</code>。我們通常在我們程式中不會具體寫出來。他是被 Haskell 用在處理語法錯誤的情況。我們目前不需要太在意 <code>fail</code>。</p>

<p>我們知道了 <code>Monad</code> typeclass 長什麼樣子，我們來看一下 <code>Maybe</code> 的 <code>Monad</code> instance。</p>
<pre class="code">instance Monad Maybe where  
    return x = Just x  
    Nothing &gt;&gt;= f = Nothing  
    Just x &gt;&gt;= f  = f x  
    fail _ = Nothing</pre>
<p><code>return</code>跟<code>pure</code>是等價的。這沒什麼困難的。我們跟我們在定義<code>Applicative</code>的時候做一樣的事，只是把他用<code>Just</code>包起來。</p>

<p><code>&gt;&gt;=</code>跟我們的<code>applyMaybe</code>是一樣的。當我們將<code>Maybe a</code>塞給我們的函數，我們保留住context，並且在輸入是<code>Nothing</code>的時候回傳<code>Nothing</code>。畢竟當沒有值的時候套用我們的函數是沒有意義的。當輸入是<code>Just</code>的時候則套用<code>f</code>並將他包在<code>Just</code>裡面。</p>

<p>我們可以試著感覺一下<code>Maybe</code>是怎樣表現成Monad的。</p>
<pre class="code">ghci&gt; return "WHAT" :: Maybe String  
Just "WHAT"  
ghci&gt; Just 9 &gt;&gt;= \x -&gt; return (x*10)  
Just 90  
ghci&gt; Nothing &gt;&gt;= \x -&gt; return (x*10)  
Nothing</pre>
<p>第一行沒什麼了不起，我們已經知道 <code>return</code> 就是 <code>pure</code> 而我們又對 <code>Maybe</code> 操作過 <code>pure</code> 了。至於下兩行就比較有趣點。</p>

<p>留意我們是如何把 <code>Just 9</code> 餵給 <code>\x -&gt; return (x*10)</code>。在函數中 <code>x</code> 綁定到 <code>9</code>。他看起好像我們能不用 pattern matching 的方式就從 <code>Maybe</code> 中抽取出值。但我們並沒有喪失掉 <code>Maybe</code> 的 context，當他是 <code>Nothing</code> 的時候，<code>&gt;&gt;=</code> 的結果也會是 <code>Nothing</code>。</p>
<a name="走鋼索"></a><h2>走鋼索</h2>

<img src="../img/pierre.png" alt="" style="float:left" class="floatleft" />
<p>我們已經知道要如何把 <code>Maybe a</code> 餵進 <code>a -&gt; Maybe b</code> 這樣的函數。我們可以看看我們如何重複使用 <code>&gt;&gt;=</code> 來處理多個 <code>Maybe a</code> 的值。</p>

<p>首先來說個小故事。皮爾斯決定要辭掉他的工作改行試著走鋼索。他對走鋼索蠻在行的，不過仍有個小問題。就是鳥會停在他拿的平衡竿上。他們會飛過來停一小會兒，然後再飛走。這樣的情況在兩邊的鳥的數量一樣時並不是個太大的問題。但有時候，所有的鳥都會想要停在同一邊，皮爾斯就失去了平衡，就會讓他從鋼索上掉下去。</p>

<p>我們這邊假設兩邊的鳥差異在三個之內的時候，皮爾斯仍能保持平衡。所以如果是右邊有一隻，左邊有四隻的話，那還撐得住。但如果左邊有五隻，那就會失去平衡。</p>

<p>我們要寫個程式來模擬整個情況。我們想看看皮爾斯究竟在好幾隻鳥來來去去後是否還能撐住。例如說，我們想看看先來了一隻鳥停在左邊，然後來了四隻停在右邊，然後左邊那隻飛走了。之後會是什麼情形。</p>

<p>我們用一對整數來代表我們的平衡竿狀態。頭一個位置代表左邊的鳥的數量，第二個位置代表右邊的鳥的數量。</p>
<pre class="code">type Birds = Int  
type Pole = (Birds,Birds)</pre>
<p>由於我們用整數來代表有多少隻鳥，我們便先來定義 <code>Int</code> 的同義型態，叫做 <code>Birds</code>。然後我們把 <code>(Birds, Birds)</code> 定義成 <code>Pole</code>。</p>

<p>接下來，我們定義一個函數他接受一個數字，然後把他放在竿子的左邊，還有另外一個函數放在右邊。</p>
<pre class="code">landLeft :: Birds -&gt; Pole -&gt; Pole  
landLeft n (left,right) = (left + n,right)  
  
landRight :: Birds -&gt; Pole -&gt; Pole  
landRight n (left,right) = (left,right + n)</pre>
<p>我們來試著執行看看：</p>
<pre class="code">ghci&gt; landLeft 2 (0,0)  
(2,0)  
ghci&gt; landRight 1 (1,2)  
(1,3)  
ghci&gt; landRight (-1) (1,2)  
(1,1)</pre>
<p>要模擬鳥飛走的話我們只要給定一個負數就好了。 由於這些操作是接受 <code>Pole</code> 並回傳 <code>Pole</code>， 所以我們可以把函數串在一起。</p>
<pre class="code">ghci&gt; landLeft 2 (landRight 1 (landLeft 1 (0,0)))  
(3,1)</pre>
<p>當我們餵 <code>(0,0)</code> 給 <code>landLeft 1</code> 時，我們會得到 <code>(1,0)</code>。接著我們模擬右邊又停了一隻鳥，狀態就變成 <code>(1,1)</code>。最後又有兩隻鳥停在左邊，狀態變成 <code>(3,1)</code>。我們這邊的寫法是先寫函數名稱，然後再套用參數。但如果先寫 pole 再寫函數名稱會比較清楚，所以我們會想定義一個函數</p>
<pre class="code">x -: f = f x</pre>
<p>我們能先套用參數然後再寫函數名稱：</p>
<pre class="code">ghci&gt; 100 -: (*3)  
300  
ghci&gt; True -: not  
False  
ghci&gt; (0,0) -: landLeft 2  
(2,0)</pre>
<p>有了這個函數，我們便能寫得比較好讀一些：</p>
<pre class="code">ghci&gt; (0,0) -: landLeft 1 -: landRight 1 -: landLeft 2  
(3,1)</pre>
<p>這個範例跟先前的範例是等價的，只不過好讀許多。很清楚的看出我們是從 <code>(0,0)</code> 開始，然後停了一隻在左邊，接著右邊又有一隻，最後左邊多了兩隻。</p>

<p>到目前為止沒什麼問題，但如果我們要停 10 隻在左邊呢？</p>
<pre class="code">ghci&gt; landLeft 10 (0,3)  
(10,3)</pre>
<p>你說左邊有 10 隻右邊卻只有 3 隻？那不是早就應該掉下去了？這個例子太明顯了，如果換個比較不明顯的例子。</p>
<pre class="code">ghci&gt; (0,0) -: landLeft 1 -: landRight 4 -: landLeft (-1) -: landRight (-2)  
(0,2)</pre>
<p>表面看起來沒什麼問題，但如果你仔細看的話，有一瞬間是右邊有四隻，但左邊沒有鳥。要修正這個錯誤，我們要重新檢視 <code>landLeft</code> 跟 <code>landRight</code>。我們其實是希望這些函數產生失敗的情況。那就是在維持平衡的時候回傳新的 pole，但失敗的時候告訴我們失敗了。這時候 <code>Maybe</code> 就剛剛好是我們要的 context 了。我們用 <code>Maybe</code> 重新寫一次：</p>
<pre class="code">landLeft :: Birds -&gt; Pole -&gt; Maybe Pole  
landLeft n (left,right)  
    | abs ((left + n) - right) &lt; 4 = Just (left + n, right)  
    | otherwise                    = Nothing  
          
landRight :: Birds -&gt; Pole -&gt; Maybe Pole  
landRight n (left,right)  
    | abs (left - (right + n)) &lt; 4 = Just (left, right + n)  
    | otherwise                    = Nothing</pre>
<p>現在這些函數不回傳 <code>Pole</code> 而回傳 <code>Maybe Pole</code> 了。他們仍接受鳥的數量跟舊的的 pole，但他們現在會檢查是否有太多鳥會造成皮爾斯失去平衡。我們用 guards 來檢查是否有差異超過三的情況。如果沒有，那就包一個在 <code>Just</code> 中的新的 pole，如果是，那就回傳 <code>Nothing</code>。</p>

<p>再來執行看看：</p>
<pre class="code">ghci&gt; landLeft 2 (0,0)  
Just (2,0)  
ghci&gt; landLeft 10 (0,3)  
Nothing</pre>
<p>一如預期，當皮爾斯不會掉下去的時候，我們就得到一個包在 <code>Just</code> 中的新 pole。當太多鳥停在同一邊的時候，我們就會拿到 <code>Nothing</code>。這樣很棒，但我們卻不知道怎麼把東西串在一起了。我們不能做 <code>landLeft 1 (landRight 1 (0,0))</code>，因為當我們對 <code>(0,0)</code> 使用 <code>landRight 1</code> 時，我們不是拿到 <code>Pole</code> 而是拿到 <code>Maybe Pole</code>。<code>landLeft 1</code> 會拿到 <code>Pole</code> 而不是拿到 <code>Maybe Pole</code>。</p>

<p>我們需要一種方法可以把拿到的 <code>Maybe Pole</code> 塞到拿 <code>Pole</code> 的函數中，然後回傳 <code>Maybe Pole</code>。而我們有 <code>&gt;&gt;=</code>，他對 <code>Maybe</code> 做的事就是我們要的</p>
<pre class="code">ghci&gt; landRight 1 (0,0) &gt;&gt;= landLeft 2  
Just (2,1)</pre>
<p><code>landLeft 2</code> 的型態是 <code>Pole -&gt; Maybe Pole</code>。我們不能餵給他 <code>Maybe Pole</code> 的東西。而 <code>landRight 1 (0,0)</code> 的結果就是 <code>Maybe Pole</code>，所以我們用 <code>&gt;&gt;=</code> 來接受一個有 context 的值然後拿給 <code>landLeft 2</code>。<code>&gt;&gt;=</code> 的確讓我們把 <code>Maybe</code> 當作有 context 的值，因為當我們丟 <code>Nothing</code> 給 <code>landLeft 2</code> 的時候，結果會是 <code>Nothing</code>。</p>
<pre class="code">ghci&gt; Nothing &gt;&gt;= landLeft 2  
Nothing</pre>
<p>這樣我們可以把這些新寫的用 <code>&gt;&gt;=</code> 串在一起。讓 monadic value 可以餵進只吃普通值的函數。</p>

<p>來看看些例子：</p>
<pre class="code">ghci&gt; return (0,0) &gt;&gt;= landRight 2 &gt;&gt;= landLeft 2 &gt;&gt;= landRight 2  
Just (2,4)</pre>
<p>我們最開始用 <code>return</code> 回傳一個 pole 並把他包在 <code>Just</code> 裡面。我們可以像往常套用 <code>landRight 2</code>，不過我們不那麼做，我們改用 <code>&gt;&gt;=</code>。<code>Just (0,0)</code> 被餵到 <code>landRight 2</code>，得到 <code>Just (0,2)</code>。接著被餵到 <code>landLeft 2</code>，得到 <code>Just (2,2)</code>。</p>

<p>還記得我們之前引入失敗情況的例子嗎？</p>
<pre class="code">ghci&gt; (0,0) -: landLeft 1 -: landRight 4 -: landLeft (-1) -: landRight (-2)  
(0,2)</pre>
<p>之前的例子並不會反應失敗的情況。但如果我們用 <code>&gt;&gt;=</code> 的話就可以得到失敗的結果。</p>
<pre class="code">ghci&gt; return (0,0) &gt;&gt;= landLeft 1 &gt;&gt;= landRight 4 &gt;&gt;= landLeft (-1) &gt;&gt;= landRight (-2)  
Nothing</pre><img src="../img/banana.png" alt="" style="float:right" class="floatright" />
<p>正如預期的，最後的情形代表了失敗的情況。我們再進一步看看這是怎麼產生的。首先 <code>return</code> 把 <code>(0,0)</code> 放到一個最小的 context 中，得到 <code>Just (0,0)</code>。然後是 <code>Just (0.0) &gt;&gt;= landLeft 1</code>。由於 <code>Just (0,0)</code> 是一個 <code>Just</code> 的值。<code>landLeft 1</code> 被套用至 <code>(0,0)</code> 而得到 <code>Just (1,0)</code>。這反應了我們仍保持在平衡的狀態。接著是 <code>Just (1,0) &gt;&gt;= landright 4</code> 而得到了 <code>Just (1,4)</code>。距離不平衡只有一步之遙了。他又被餵給 <code>landLeft (-1)</code>，這組合成了 <code>landLeft (-1) (1,4)</code>。由於失去了平衡，我們變得到了 <code>Nothing</code>。而我們把 <code>Nothing</code> 餵給 <code>landRight (-2)</code>，由於他是 <code>Nothing</code>，也就自動得到了 <code>Nothing</code>。</p>

<p>如果只把 <code>Maybe</code> 當作 applicative 用的話是沒有辦法達到我們要的效果的。你試著做一遍就會卡住。因為 applicative functor 並不允許 applicative value 之間有彈性的互動。他們最多就是讓我們可以用 applicative style 來傳遞參數給函數。applicative operators 能拿到他們的結果並把他用 applicative 的方式餵給另一個函數，並把最終的 applicative 值放在一起。但在每一步之間並沒有太多允許我們作手腳的機會。而我們的範例需要每一步都倚賴前一步的結果。當每一隻鳥降落的時候，我們都會把前一步的結果拿出來看看。好知道結果到底應該成功或失敗。</p>

<p>我們也能寫出一個函數，完全不管現在究竟有幾隻鳥停在竿子上，只是要害皮爾斯滑倒。我們可以稱呼這個函數叫做 <code>banana</code>：</p>
<pre class="code">banana :: Pole -&gt; Maybe Pole  
banana _ = Nothing</pre>
<p>現在我們能把香蕉皮串到我們的過程中。他絕對會讓遇到的人滑倒。他完全不管前面的狀態是什麼都會產生失敗。</p>
<pre class="code">ghci&gt; return (0,0) &gt;&gt;= landLeft 1 &gt;&gt;= banana &gt;&gt;= landRight 1  
Nothing</pre>
<p><code>Just (1,0)</code> 被餵給 <code>banana</code>，而產生了 <code>Nothing</code>，之後所有的結果便都是 <code>Nothing</code> 了。</p>

<p>要同樣表示這種忽略前面的結果，只注重眼前的 monadic value 的情況，其實我們可以用 <code>&gt;&gt;</code> 來表達。</p>
<pre class="code">(&gt;&gt;) :: (Monad m) =&gt; m a -&gt; m b -&gt; m b  
m &gt;&gt; n = m &gt;&gt;= \_ -&gt; n</pre>
<p>一般來講，碰到一個完全忽略前面狀態的函數，他就應該只會回傳他想回傳的值而已。但碰到 Monad，他們的 context 還是必須要被考慮到。來看一下 <code>&gt;&gt;</code> 串接 <code>Maybe</code> 的情況。</p>
<pre class="code">ghci&gt; Nothing &gt;&gt; Just 3  
Nothing  
ghci&gt; Just 3 &gt;&gt; Just 4  
Just 4  
ghci&gt; Just 3 &gt;&gt; Nothing  
Nothing</pre>
<p>如果你把 <code>&gt;&gt;</code> 換成 <code>&gt;&gt;= \_ -&gt;</code>，那就很容易看出他的意思。</p>

<p>我們也可以把 <code>banana</code> 改用 <code>&gt;&gt;</code> 跟 <code>Nothing</code> 來表達：</p>
<pre class="code">ghci&gt; return (0,0) &gt;&gt;= landLeft 1 &gt;&gt; Nothing &gt;&gt;= landRight 1  
Nothing</pre>
<p>我們得到了保證的失敗。</p>

<p>我們也可以看看假如我們故意不用把 <code>Maybe</code> 視為有 context 的值的寫法。他會長得像這樣：</p>
<pre class="code">routine :: Maybe Pole  
routine = case landLeft 1 (0,0) of  
    Nothing -&gt; Nothing  
    Just pole1 -&gt; case landRight 4 pole1 of   
            Nothing -&gt; Nothing  
            Just pole2 -&gt; case landLeft 2 pole2 of  
                    Nothing -&gt; Nothing  
                    Just pole3 -&gt; landLeft 1 pole3</pre><img src="../img/centaur.png" alt="" style="float:right" class="floatright" />
<p>左邊先停了一隻鳥，然後我們停下來檢查有沒有失敗。當失敗的時候我們回傳 <code>Nothing</code>。當成功的時候，我們在右邊停一隻鳥，然後再重複前面做的事情。把這些瑣事轉換成 <code>&gt;&gt;=</code> 證明了 <code>Maybe</code> Monad 的力量，可以省去我們不少的時間。</p>

<p>注意到 <code>Maybe</code> 對 <code>&gt;&gt;=</code> 的實作，他其實就是在做碰到 <code>Nothing</code> 就會傳 <code>Nothing</code>，碰到正確值就繼續用 <code>Just</code> 傳遞值。</p>

<p>在這個章節中，我們看過了好幾個函數，也見識了用 <code>Maybe</code> monad 來表示失敗的 context 的力量。把普通的函數套用換成了 <code>&gt;&gt;=</code>，讓我們可以輕鬆地應付可能會失敗的情況，並幫我們傳遞 context。這邊的 context 就代表失敗的可能性，當我們套用函數到 context 的時候，就代表考慮進了失敗的情況。</p>
<a name="do_表示法"></a><h2>do 表示法</h2>


<p>Monad 在 Haskell 中是十分重要的，所以我們還特別為了操作他設置了特別的語法：<code>do</code> 表示法。我們在介紹 I/O 的時候已經用過 <code>do</code> 來把小的 I/O action 串在一起了。其實 <code>do</code> 並不只是可以用在 <code>IO</code>，他可以用在任何 monad 上。他的原則是簡單明瞭，把 monadic value 串成一串。我們這邊來細看 <code>do</code> 是如何使用，以及為什麼我們十分倚賴他。</p>

<p>來看一下熟悉的例子：</p>
<pre class="code">ghci&gt; Just 3 &gt;&gt;= (\x -&gt; Just (show x ++ "!"))  
Just "3!"</pre>
<p>你說這沒什麼了不起，不過就是把 monadic value 餵給一個函數罷了。其中 <code>x</code> 就指定成 <code>3</code>。也從 monadic value 變成了普通值。那如果我們要在 lambda 中使用 <code>&gt;&gt;=</code> 呢？</p>
<pre class="code">ghci&gt; Just 3 &gt;&gt;= (\x -&gt; Just "!" &gt;&gt;= (\y -&gt; Just (show x ++ y)))  
Just "3!"</pre>
<p>我們嵌一個 <code>&gt;&gt;=</code> 在另外一個 <code>&gt;&gt;=</code> 中。在外層的 lambda，我們把 <code>Just "!"</code> 餵給 <code>\y -&gt; Just (show x ++ y)</code>。在內層的 lambda，<code>y</code> 被指定成 <code>"!"</code>。<code>x</code> 仍被指定成 <code>3</code>，是因為我們是從外層的 lambda 取值的。這些行為讓我們回想到下列式子：</p>
<pre class="code">ghci&gt; let x = 3; y = "!" in show x ++ y  
"3!"</pre>
<p>差別在於前述的值是 monadic，具有失敗可能性的 context。我們可以把其中任何一步代換成失敗的狀態：</p>
<pre class="code">ghci&gt; Nothing &gt;&gt;= (\x -&gt; Just "!" &gt;&gt;= (\y -&gt; Just (show x ++ y)))  
Nothing  
ghci&gt; Just 3 &gt;&gt;= (\x -&gt; Nothing &gt;&gt;= (\y -&gt; Just (show x ++ y)))  
Nothing  
ghci&gt; Just 3 &gt;&gt;= (\x -&gt; Just "!" &gt;&gt;= (\y -&gt; Nothing))  
Nothing</pre>
<p>第一行中，把 <code>Nothing</code> 餵給一個函數，很自然地會回傳 <code>Nothing</code>。第二行裡，我們把 <code>Just 3</code> 餵給一個函數，所以 <code>x</code> 就成了 <code>3</code>。但我們把 <code>Nothing</code> 餵給內層的 lambda 所有的結果就成了 <code>Nothing</code>，這也進一步使得外層的 lambda 成了 <code>Nothing</code>。這就好比我們在 <code>let</code> expression 中來把值指定給變數一般。只差在我們這邊的值是 monadic value。</p>

<p>要再說得更清楚點，我們來把 script 改寫成每行都處理一個 <code>Maybe</code>：</p>
<pre class="code">foo :: Maybe String  
foo = Just 3   &gt;&gt;= (\x -&gt; 
      Just "!" &gt;&gt;= (\y -&gt; 
      Just (show x ++ y)))</pre>
<p>為了擺脫這些煩人的 lambda，Haskell 允許我們使用 <code>do</code> 表示法。他讓我們可以把先前的程式寫成這樣：</p>
<pre class="code">foo :: Maybe String  
foo = do  
    x &lt;- Just 3  
    y &lt;- Just "!"  
    Just (show x ++ y)</pre><img src="../img/owld.png" alt="" style="float:right" class="floatright" />
<p>這看起來好像讓我們不用在每一步都去檢查 <code>Maybe</code> 的值究竟是 <code>Just</code> 或 <code>Nothing</code>。這蠻方便的，如果在任何一個步驟我們取出了 <code>Nothing</code>。那整個 <code>do</code> 的結果就會是 <code>Nothing</code>。我們把整個責任都交給 <code>&gt;&gt;=</code>，他會幫我們處理所有 context 的問題。這邊的 <code>do</code> 表示法不過是另外一種語法的形式來串連所有的 monadic value 罷了。</p>

<p>在 <code>do</code> expression 中，每一行都是一個 monadic value。要檢查處理的結果的話，就要使用 <code>&lt;-</code>。如果我們拿到一個 <code>Maybe String</code>，並用 <code>&lt;-</code> 來綁定給一個變數，那個變數就會是一個 <code>String</code>，就像是使用 <code>&gt;&gt;=</code> 來將 monadic value 帶給 lambda 一樣。至於 <code>do</code> expression 中的最後一個值，好比說 <code>Just (show x ++ y)</code>，就不能用 <code>&lt;-</code> 來綁定結果，因為那樣的寫法當轉換成 <code>&gt;&gt;=</code> 的結果時並不合理。他必須要是所有 monadic value 黏起來後的總結果，要考慮到前面所有可能失敗的情形。</p>

<p>舉例來說，來看看下面這行：</p>
<pre class="code">ghci&gt; Just 9 &gt;&gt;= (\x -&gt; Just (x &gt; 8))  
Just True</pre>
<p>由於 <code>&gt;&gt;=</code> 左邊的參數是一個 <code>Just</code> 型態的值，當 lambda 被套用至 <code>9</code> 就會得到 <code>Just True</code>。如果我們重寫整個式子，改用 <code>do</code> 表示法：我們會得到：</p>
<pre class="code">marySue :: Maybe Bool  
marySue = do   
    x &lt;- Just 9  
    Just (x &gt; 8)</pre>
<p>如果我們比較這兩種寫法，就很容易看出為什麼整個 monadic value 的結果會是在 <code>do</code> 表示法中最後一個 monadic value 的值。他串連了全面所有的結果。</p>

<p>我們走鋼索的模擬程式也可以改用 <code>do</code> 表示法重寫。<code>landLeft</code> 跟 <code>landRight</code> 接受一個鳥的數字跟一個竿子來產生一個包在 <code>Just</code> 中新的竿子。而在失敗的情況會產生 <code>Nothing</code>。我們使用 <code>&gt;&gt;=</code> 來串連所有的步驟，每一步都倚賴前一步的結果，而且都帶有可能失敗的 context。這邊有一個範例，先是有兩隻鳥停在左邊，接著有兩隻鳥停在右邊，然後是一隻鳥停在左邊：</p>
<pre class="code">routine :: Maybe Pole  
routine = do  
    start &lt;- return (0,0)  
    first &lt;- landLeft 2 start  
    second &lt;- landRight 2 first  
    landLeft 1 second</pre>
<p>我們來看看成功的結果：</p>
<pre class="code">ghci&gt; routine  
Just (3,2)</pre>
<p>當我們要把這些 routine 用具體寫出的 <code>&gt;&gt;=</code>，我們會這樣寫：<code>return (0,0) &gt;&gt;= landLeft 2</code>，而有了 <code>do</code> 表示法，每一行都必須是一個 monadic value。所以我們清楚地把前一個 <code>Pole</code> 傳給 <code>landLeft</code> 跟 <code>landRight</code>。如果我們檢視我們綁定 <code>Maybe</code> 的變數，<code>start</code> 就是 <code>(0,0)</code>，而 <code>first</code> 就會是 <code>(2,0)</code>。</p>

<p>由於 <code>do</code> 表示法是一行一行寫，他們會看起來很像是命令式的寫法。但實際上他們只是代表序列而已，每一步的值都倚賴前一步的結果，並帶著他們的 context 繼續下去。</p>

<p>我們再重新來看看如果我們沒有善用 <code>Maybe</code> 的 monad 性質的程式：</p>
<pre class="code">routine :: Maybe Pole  
    routine =   
        case Just (0,0) of   
            Nothing -&gt; Nothing  
            Just start -&gt; case landLeft 2 start of  
                Nothing -&gt; Nothing  
                Just first -&gt; case landRight 2 first of  
                    Nothing -&gt; Nothing  
                    Just second -&gt; landLeft 1 second</pre>
<p>在成功的情形下，<code>Just (0,0)</code> 變成了 <code>start</code>，</p>

<p>而 <code>landLeft 2 start</code> 的結果成了 <code>first</code>。</p>

<p>如果我們想在 <code>do</code> 表示法裡面對皮爾斯丟出香蕉皮，我們可以這樣做：</p>
<pre class="code">routine :: Maybe Pole  
routine = do  
    start &lt;- return (0,0)  
    first &lt;- landLeft 2 start  
    Nothing  
    second &lt;- landRight 2 first  
    landLeft 1 second</pre>
<p>當我們在 <code>do</code> 表示法寫了一行運算，但沒有用到 <code>&lt;-</code> 來綁定值的話，其實實際上就是用了 <code>&gt;&gt;</code>，他會忽略掉計算的結果。我們只是要讓他們有序，而不是要他們的結果，而且他比寫成 <code>_ &lt;- Nothing</code> 要來得漂亮的多。</p>

<p>你會問究竟我們何時要使用 <code>do</code> 表示法或是 <code>&gt;&gt;=</code>，這完全取決於你的習慣。在這個例子由於有每一步都倚賴於前一步結果的特性，所以我們使用 <code>&gt;&gt;=</code>。如果用 <code>do</code> 表示法，我們就必須清楚寫出鳥究竟是停在哪根竿子上，但其實每一次都是前一次的結果。不過他還是讓我們了解到怎麼使用 <code>do</code>。</p>

<p>在 <code>do</code> 表示法中，我們其實可以用模式匹配來綁定 monadic value，就好像我們在 <code>let</code> 表達式，跟函數參數中使用模式匹配一樣。這邊來看一個在 <code>do</code> 表示法中使用模式匹配的範例： </p>
<pre class="code">justH :: Maybe Char  
justH = do  
    (x:xs) &lt;- Just "hello"  
    return x</pre>
<p>我們用模式匹配來取得 <code>"hello"</code> 的第一個字元，然後回傳結果。所以 <code>justH</code> 計算會得到 <code>Just 'h'</code>。</p>

<p>如果模式匹配失敗怎麼辦？當定義一個函數的時候，一個模式不匹配就會跳到下一個模式。如果所有都不匹配，那就會造成錯誤，整個程式就當掉。另一方面，如果在 <code>let</code> 中進行模式匹配失敗會直接造成錯誤。畢竟在 <code>let</code> 表達式的情況下並沒有失敗就跳下一個的設計。至於在 <code>do</code> 表示法中模式匹配失敗的話，那就會呼叫 <code>fail</code> 函數。他定義在 <code>Monad</code> 的 type class 定義豬。他允許在現在的 monad context 底下，失敗只會造成失敗而不會讓整個程式當掉。他預設的實作如下：</p>
<pre class="code">fail :: (Monad m) =&gt; String -&gt; m a  
fail msg = error msg</pre>
<p>可見預設的實作的確是讓程式掛掉，但在某些考慮到失敗的可能性的 Monad（像是 <code>Maybe</code>）常常會有他們自己的實作。對於 <code>Maybe</code>，他的實作像是這樣：</p>
<pre class="code">fail _ = Nothing</pre>
<p>他忽略錯誤訊息，並直接回傳 <code>Nothing</code>。所以當在 <code>do</code> 表示法中的 <code>Maybe</code> 模式匹配失敗的時候，整個結果就會是 <code>Nothing</code>。這種方式比起讓程式掛掉要好多了。這邊來看一下 <code>Maybe</code> 模式匹配失敗的範例：</p>
<pre class="code">wopwop :: Maybe Char  
wopwop = do  
    (x:xs) &lt;- Just ""  
    return x</pre>
<p>模式匹配的失敗，所以那一行的效果相當於一個 <code>Nothing</code>。我們來看看執行結果：</p>
<pre class="code">ghci&gt; wopwop  
Nothing</pre>
<p>這樣模式匹配的失敗只會限制在我們 monad 的 context 中，而不是整個程式的失敗。這種處理方式要好多了。</p>
<a name="List_Monad"></a><h2>List Monad</h2>

<img src="../img/deadcat.png" alt="" style="float:left" class="floatleft" />
<p>我們已經了解了 <code>Maybe</code> 可以被看作具有失敗可能性 context 的值，也見識到如何用 <code>&gt;&gt;=</code> 來把這些具有失敗考量的值傳給函數。在這一個章節中，我們要看一下如何利用 list 的 monadic 的性質來寫 non-deterministic 的程式。</p>

<p>我們已經討論過在把 list 當作 applicatives 的時候他們具有 non-deterministic 的性質。像 <code>5</code> 這樣一個值是 deterministic 的。他只有一種結果，而且我們清楚的知道他是什麼結果。另一方面，像 <code>[3,8,9]</code> 這樣的值包含好幾種結果，所以我們能把他看作是同時具有好幾種結果的值。把 list 當作 applicative functors 展示了這種特性：</p>
<pre class="code">ghci&gt; (*) &lt;$&gt; [1,2,3] &lt;*&gt; [10,100,1000]  
[10,100,1000,20,200,2000,30,300,3000]</pre>
<p>將左邊 list 中的元素乘上右邊 list 中的元素這樣所有的組合全都被放進結果的 list 中。當處理 non-determinism 的時候，這代表我們有好幾種選擇可以選，我們也會每種選擇都試試看，因此最終的結果也會是一個 non-deterministic 的值。只是包含更多不同可能罷了。</p>

<p>non-determinism 這樣的 context 可以被漂亮地用 monad 來考慮。所以我們這就來看看 list 的 <code>Monad</code> instance 的定義：</p>
<pre class="code">instance Monad [] where  
    return x = [x]  
    xs &gt;&gt;= f = concat (map f xs)  
    fail _ = []</pre>
<p><code>return</code> 跟 <code>pure</code> 是做同樣的事，所以我們應該算已經理解了 <code>return</code> 的部份。他接受一個值，並把他放進一個最小的一個 context 中。換種說法，就是他做了一個只包含一個元素的 list。這樣對於我們想要操作普通值的時候很有用，可以直接把他包起來變成 non-deterministic value。</p>

<p>要理解 <code>&gt;&gt;=</code> 在 list monad 的情形下是怎麼運作的，讓我們先來回歸基本。<code>&gt;&gt;=</code> 基本上就是接受一個有 context 的值，把他餵進一個只接受普通值的函數，並回傳一個具有 context 的值。如果操作的函數只會回傳普通值而不是具有 context 的值，那 <code>&gt;&gt;=</code> 在操作一次後就會失效，因為 context 不見了。讓我們來試著把一個 non-deterministic value 塞到一個函數中：</p>
<pre class="code">ghci&gt; [3,4,5] &gt;&gt;= \x -&gt; [x,-x]  
[3,-3,4,-4,5,-5]</pre>
<p>當我們對 <code>Maybe</code> 使用 <code>&gt;&gt;=</code>，是有考慮到可能失敗的 context。在這邊 <code>&gt;&gt;=</code> 則是有考慮到 non-determinism。<code>[3,4,5]</code> 是一個 non-deterministic value，我們把他餵給一個回傳 non-deterministic value 的函數。那結果也會是 non-deterministic。而且他包含了所有從 <code>[3,4,5]</code> 取值，套用 <code>\x -&gt; [x,-x]</code> 後的結果。這個函數他接受一個數值並產生兩個數值，一個原來的數值與取過負號的數值。當我們用 <code>&gt;&gt;=</code> 來把一個 list 餵給這個函數，所有在 list 中的數值都保留了原有的跟取負號過的版本。<code>x</code> 會針對 list 中的每個元素走過一遍。</p>

<p>要看看結果是如何算出來的，只要看看實作就好了。首先我們從 <code>[3,4,5]</code> 開始。然後我們用 lambda 映射過所有元素得到：</p>
<pre class="code">[[3,-3],[4,-4],[5,-5]]</pre>
<p>lambda 會掃過每個元素，所以我們有一串包含一堆 list 的 list，最後我們在把這些 list 壓扁，得到一層的 list。這就是我們得到 non-deterministic value 的過程。</p>

<p>non-determinism 也有考慮到失敗的可能性。<code>[]</code> 其實等價於 <code>Nothing</code>，因為他什麼結果也沒有。所以失敗等同於回傳一個空的 list。所有的錯誤訊息都不用。讓我們來看看範例：</p>
<pre class="code">ghci&gt; [] &gt;&gt;= \x -&gt; ["bad","mad","rad"]  
[]  
ghci&gt; [1,2,3] &gt;&gt;= \x -&gt; []  
[]</pre>
<p>第一行裡面，一個空的 list 被丟給 lambda。因為 list 沒有任何元素，所以函數收不到任何東西而產生空的 list。這跟把 <code>Nothing</code> 餵給函數一樣。第二行中，每一個元素都被餵給函數，但所有元素都被丟掉，而只回傳一個空的 list。因為所有的元素都造成了失敗，所以整個結果也代表失敗。</p>

<p>就像 <code>Maybe</code> 一樣，我們可以用 <code>&gt;&gt;=</code> 把他們串起來：</p>
<pre class="code">ghci&gt; [1,2] &gt;&gt;= \n -&gt; ['a','b'] &gt;&gt;= \ch -&gt; return (n,ch)  
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]</pre><img src="../img/concatmap.png" alt="" style="float:left" class="floatleft" />
<p><code>[1,2]</code> 被綁定到 <code>n</code> 而 <code>['a','b']</code> 被綁定到 <code>ch</code>。最後我們用 <code>return (n,ch)</code> 來把他放到一個最小的 context 中。在這個案例中，就是把 <code>(n,ch)</code> 放到 list 中，這代表最低程度的 non-determinism。整套結構要表達的意思就是對於 <code>[1,2]</code> 的每個元素，以及 <code>['a','b']</code> 的每個元素，我們產生一個 tuple，每項分別取自不同的 list。</p>

<p>一般來說，由於 <code>return</code> 接受一個值並放到最小的 context 中，他不會多做什麼額外的東西僅僅是展示出結果而已。</p>
<blockquote>
<p>當你要處理 non-deterministic value 的時候，你可以把 list 中的每個元素想做計算路線的一個 branch。</p>
</blockquote>

<p>這邊把先前的表達式用 <code>do</code> 重寫：</p>
<pre class="code">listOfTuples :: [(Int,Char)]  
listOfTuples = do  
    n &lt;- [1,2]  
    ch &lt;- ['a','b']  
    return (n,ch)</pre>
<p>這樣寫可以更清楚看到 <code>n</code> 走過 <code>[1,2]</code> 中的每一個值，而 <code>ch</code> 則取過 <code>['a','b']</code> 中的每個值。正如 <code>Maybe</code> 一般，我們從 monadic value 中取出普通值然後餵給函數。<code>&gt;&gt;=</code> 會幫我們處理好一切 context 相關的問題，只差在這邊的 context 指的是 non-determinism。</p>

<p>使用 <code>do</code> 來對 list 操作讓我們回想起之前看過的一些東西。來看看下列的片段：</p>
<pre class="code">ghci&gt; [ (n,ch) | n &lt;- [1,2], ch &lt;- ['a','b'] ]  
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]</pre>
<p>沒錯，就是 list comprehension。在先前的範例中，<code>n</code> 會走過 <code>[1,2]</code> 的每個元素，而 <code>ch</code> 會走過 <code>['a','b']</code> 的每個元素。同時我們又把 <code>(n,ch)</code> 放進一個 context 中。這跟 list comprehension 的目的一樣，只是我們在 list comprehension 裡面不用在最後寫一個 <code>return</code> 來得到 <code>(n,ch)</code> 的結果。</p>

<p>實際上，list comprehension 不過是一個語法糖。不論是 list comprehension 或是用 <code>do</code> 表示法來表示，他都會轉換成用 <code>&gt;&gt;=</code> 來做計算。</p>

<p>List comprehension 允許我們 filter 我們的結果。舉例來說，我們可以只要包含 <code>7</code> 在表示位數裡面的數值。</p>
<pre class="code">ghci&gt; [ x | x &lt;- [1..50], '7' `elem` show x ]  
[7,17,27,37,47]</pre>
<p>我們用 <code>show</code> 跟 <code>x</code> 來把數值轉成字串，然後檢查 <code>'7'</code> 是否包含在字串裡面。要看看 filtering 要如何轉換成用 list monad 來表達，我們可以考慮使用 <code>guard</code> 函數，還有 <code>MonadPlus</code> 這個 type class。<code>MonadPlus</code> 這個 type class 是用來針對可以同時表現成 monoid 的 monad。下面是他的定義：</p>
<pre class="code">class Monad m =&gt; MonadPlus m where  
    mzero :: m a  
    mplus :: m a -&gt; m a -&gt; m a</pre>
<p><code>mzero</code> 是其實是 <code>Monoid</code> 中 <code>mempty</code> 的同義詞，而 <code>mplus</code> 則對應到 <code>mappend</code>。因為 list 同時是 monoid 跟 monad，他們可以是 <code>MonadPlus</code> 的 instance。</p>
<pre class="code">instance MonadPlus [] where  
    mzero = []  
    mplus = (++)</pre>
<p>對於 list 而言，<code>mzero</code> 代表的是不產生任何結果的 non-deterministic value，也就是失敗的結果。而 <code>mplus</code> 則把兩個 non-deterministic value 結合成一個。<code>guard</code> 這個函數被定義成下列形式：</p>
<pre class="code">guard :: (MonadPlus m) =&gt; Bool -&gt; m ()  
guard True = return ()  
guard False = mzero</pre>
<p>這函數接受一個布林值，如果他是 <code>True</code> 就回傳一個包在預設 context 中的 <code>()</code>。如果他失敗就產生 mzero。</p>
<pre class="code">ghci&gt; guard (5 &gt; 2) :: Maybe ()  
Just ()  
ghci&gt; guard (1 &gt; 2) :: Maybe ()  
Nothing  
ghci&gt; guard (5 &gt; 2) :: [()]  
[()]  
ghci&gt; guard (1 &gt; 2) :: [()]  
[]</pre>
<p>看起來蠻有趣的，但用起來如何呢？我們可以用他來過濾 non-deterministic 的計算。</p>
<pre class="code">ghci&gt; [1..50] &gt;&gt;= (\x -&gt; guard ('7' `elem` show x) &gt;&gt; return x)  
[7,17,27,37,47]</pre>
<p>這邊的結果跟我們之前 list comprehension 的結果一致。究竟 <code>guard</code> 是如何辦到的？我們先看看 <code>guard</code> 跟 <code>&gt;&gt;</code> 是如何互動：</p>
<pre class="code">ghci&gt; guard (5 &gt; 2) &gt;&gt; return "cool" :: [String]  
["cool"]  
ghci&gt; guard (1 &gt; 2) &gt;&gt; return "cool" :: [String]  
[]</pre>
<p>如果 <code>guard</code> 成功的話，結果就會是一個空的 tuple。接著我們用 <code>&gt;&gt;</code> 來忽略掉空的 tuple，而呈現不同的結果。另一方面，如果 <code>guard</code> 失敗的話，後面的 <code>return</code> 也會失敗。這是因為用 <code>&gt;&gt;=</code> 把空的 list 餵給函數總是會回傳空的 list。基本上 <code>guard</code> 的意思就是：如果一個布林值是 <code>False</code> 那就產生一個失敗狀態，不然的話就回傳一個基本的 <code>()</code>。這樣計算就可以繼續進行。</p>

<p>這邊我們把先前的範例用 <code>do</code> 改寫：</p>
<pre class="code">sevensOnly :: [Int]  
sevensOnly = do  
    x &lt;- [1..50]  
    guard ('7' `elem` show x)  
    return x</pre>
<p>如果我們不寫最後一行 <code>return x</code>，那整個 list 就會是包含一堆空 tuple 的 list。</p>

<p>把上述範例寫成 list comprehension 的話就會像這樣：</p>
<pre class="code">ghci&gt; [ x | x &lt;- [1..50], '7' `elem` show x ]  
[7,17,27,37,47]</pre>
<p>所以 list comprehension 的 filtering 基本上跟 <code>guard</code> 是一致的。</p>
<a name="A_knight's_quest"></a><h3>A knight's quest</h3>


<p>這邊來看一個可以用 non-determinism 解決的問題。假設你有一個西洋棋盤跟一隻西洋棋中的騎士擺在上面。我們希望知道是否這隻騎士可以在三步之內移到我們想要的位置。我們只要用一對數值來表示騎士在棋盤上的位置。第一個數值代表棋盤的行，而第二個數值代表棋盤的列。</p>
<img src="../img/chess.png" alt="" style="float:none" class="floatnone" />
<p>我們先幫騎士的位置定義一個 type synonym。</p>
<pre class="code">type KnightPos = (Int,Int)</pre>
<p>假設騎士現在是在 <code>(6,2)</code>。究竟他能不能夠在三步內移動到 <code>(6,1)</code> 呢？你可能會先考慮究竟哪一步是最佳的一步。但不如全部一起考慮吧！要好好利用所謂的 non-determinism。所以我們不是只選擇一步，而是選擇全部。我們先寫一個函數回傳所有可能的下一步：</p>
<pre class="code">moveKnight :: KnightPos -&gt; [KnightPos]  
moveKnight (c,r) = do  
    (c',r') &lt;- [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)  
                ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)  
                ]  
    guard (c' `elem` [1..8] &amp;&amp; r' `elem` [1..8])
    return (c',r')</pre>
<p>騎士有可能水平或垂直移動一步或二步，但問題是他們必須要同時水平跟垂直移動。<code>(c',r')</code> 走過 list 中的每一個元素，而 <code>guard</code> 會保證產生的結果會停留在棋盤上。如果沒有，那就會產生一個空的 list，表示失敗的結果，<code>return (c',r')</code> 也就不會被執行。</p>

<p>這個函數也可以不用 list monad 來寫，但我們這邊只是寫好玩的。下面是一個用 <code>filter</code> 實現的版本：</p>
<pre class="code">moveKnight :: KnightPos -&gt; [KnightPos]  
moveKnight (c,r) = filter onBoard  
    [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)  
    ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)  
    ]  
    where onBoard (c,r) = c `elem` [1..8] &amp;&amp; r `elem` [1..8]</pre>
<p>兩個函數做的都是相同的事，所以選個你喜歡的吧。</p>
<pre class="code">ghci&gt; moveKnight (6,2)  
[(8,1),(8,3),(4,1),(4,3),(7,4),(5,4)]  
ghci&gt; moveKnight (8,1)  
[(6,2),(7,3)]</pre>
<p>我們接受一個位置然後產生所有可能的移動方式。所以我們有一個 non-deterministic 的下一個位置。我們用 <code>&gt;&gt;=</code> 來餵給 <code>moveKnight</code>。接下來我們就可以寫一個三步內可以達到的所有位置：</p>
<pre class="code">in3 :: KnightPos -&gt; [KnightPos]  
in3 start = do   
    first &lt;- moveKnight start  
    second &lt;- moveKnight first  
    moveKnight second</pre>
<p>如果你傳 <code>(6,2)</code>，得到的 list 會很大，因為會有不同種方式來走到同樣的一個位置。我們也可以不用 <code>do</code> 來寫：</p>
<pre class="code">in3 start = return start &gt;&gt;= moveKnight &gt;&gt;= moveKnight &gt;&gt;= moveKnight</pre>
<p>第一次 <code>&gt;&gt;=</code> 給我們移動一步的所有結果，第二次 <code>&gt;&gt;=</code> 給我們移動兩步的所有結果，第三次則給我們移動三步的所有結果。</p>

<p>用 <code>return</code> 來把一個值放進預設的 context 然後用 <code>&gt;&gt;=</code> 餵給一個函數其實跟函數呼叫是同樣的，只是用不同的寫法而已。</p>

<p>接著我們寫一個函數接受兩個位置，然後可以測試是否可以在三步內從一個位置移到另一個位置：</p>
<pre class="code">canReachIn3 :: KnightPos -&gt; KnightPos -&gt; Bool  
canReachIn3 start end = end `elem` in3 start</pre>
<p>我們產生所有三步的可能位置，然後看看其中一個位置是否在裡面。所以我們可以看看是否可以在三步內從 <code>(6,2)</code> 走到 <code>(6,1)</code>：</p>
<pre class="code">ghci&gt; (6,2) `canReachIn3` (6,1)  
True</pre>
<p>那從 <code>(6,2)</code> 到 <code>(7,3)</code> 呢？</p>
<pre class="code">ghci&gt; (6,2) `canReachIn3` (7,3)  
False</pre>
<p>答案是不行。你可以修改函數改成當可以走到的時候，他還會告訴你實際的步驟。之後你也可以改成不只限定成三步，可以任意步。</p>
<a name="Monad_laws_(單子律)"></a><h2>Monad laws (單子律)</h2>

<img src="../img/judgedog.png" alt="" style="float:right" class="floatright" />
<p>正如 applicative functors 以及 functors，Monad 也有一些要遵守的定律。我們定義一個 <code>Monad</code> 的 instance 並不代表他是一個 monad，只代表他被定義成那個 type class 的 instance。一個型態要是 monad，則必須遵守單子律。這些定律讓我們可以對這個型態的行為做一些合理的假設。</p>

<p>Haskell 允許任何型態是任何 type class 的 instance。但他不會檢查單子律是否有被遵守，所以如果我們要寫一個 <code>Monad</code> 的 instance，那最好我們確定他有遵守單子律。我們可以不用擔心標準函式庫中的型態是否有遵守單子律。但之後我們定義自己的型態時，我們必須自己檢查是否有遵守單子律。不用擔心，他們不會很複雜。</p>
<a name="Left_identity"></a><h3>Left identity</h3>


<p>單子律的第一項說當我們接受一個值，將他用 <code>return</code> 放進一個預設的 context 並把他用 <code>&gt;&gt;=</code> 餵進一個函數的結果，應該要跟我們直接做函數呼叫的結果一樣。</p>

<p>  * <code>retrun x &gt;&gt;= f</code> 應該等於 <code>f x</code></p>

<p>如果你是把 monadic value 視為把一個值放進最小的 context 中，僅僅是把同樣的值放進結果中的話， 那這個定律應該很直覺。因為把這個值放進 context 中然後丟給函數，應該要跟直接把這個值丟給函數做呼叫應該沒有差別。</p>

<p>對於 <code>Maybe</code> monad，<code>return</code> 被定義成 <code>Just</code>。<code>Maybe</code> monad 講的是失敗的可能性，如果我們有普通值要把他放進 context 中，那把這個動作當作是計算成功應該是很合理的，畢竟我們都知道那個值是很具體的。這邊有些範例：</p>
<pre class="code">ghci&gt; return 3 &gt;&gt;= (\x -&gt; Just (x+100000))  
Just 100003  
ghci&gt; (\x -&gt; Just (x+100000)) 3  
Just 100003</pre>
<p>對於 list monad 而言，<code>return</code> 是把值放進一個 list 中，變成只有一個元素的 list。<code>&gt;&gt;=</code> 則會走過 list 中的每個元素，並把他們丟給函數做運算，但因為在單一元素的 list 中只有一個值，所以跟直接對那元素做運算是等價的：</p>
<pre class="code">ghci&gt; return "WoM" &gt;&gt;= (\x -&gt; [x,x,x])  
["WoM","WoM","WoM"]  
ghci&gt; (\x -&gt; [x,x,x]) "WoM"  
["WoM","WoM","WoM"]</pre>
<p>至於 <code>IO</code>，我們已經知道 <code>return</code> 並不會造成副作用，只不過是在結果中呈現原有值。所以這個定律對於 <code>IO</code> 也是有效的。</p>
<a name="Right_identity"></a><h3>Right identity</h3>


<p>單子律的第二個規則是如果我們有一個 monadic value，而且我們把他用 <code>&gt;&gt;=</code> 餵給 <code>return</code>，那結果就會是原有的 monadic value。</p>

<p>  * <code>m &gt;&gt;= return</code> 會等於 <code>m</code></p>

<p>這一個可能不像第一定律那麼明顯，但我們還是來看看為什麼會遵守這條。當我們把一個 monadic value 用 <code>&gt;&gt;=</code> 餵給函數，那些函數是接受普通值並回傳具有 context 的值。<code>return</code> 也是在他們其中。如果你仔細看他的型態，<code>return</code> 是把一個普通值放進一個最小 context 中。這就表示，對於 <code>Maybe</code> 他並沒有造成任何失敗的狀態，而對於 list 他也沒有多加 non-determinism。</p>
<pre class="code">ghci&gt; Just "move on up" &gt;&gt;= (\x -&gt; return x)  
Just "move on up"  
ghci&gt; [1,2,3,4] &gt;&gt;= (\x -&gt; return x)  
[1,2,3,4]  
ghci&gt; putStrLn "Wah!" &gt;&gt;= (\x -&gt; return x)  
Wah!</pre>
<p>如果我們仔細檢視 list monad 的範例，會發現 <code>&gt;&gt;=</code> 的實作是：</p>
<pre class="code">xs &gt;&gt;= f = concat (map f xs)</pre>
<p>所以當我們將 <code>[1,2,3,4]</code> 丟給 <code>return</code>，第一個 <code>return</code> 會把 <code>[1,2,3,4]</code> 映射成 <code>[[1],[2],[3],[4]]</code>，然後再把這些小 list 串接成我們原有的 list。</p>

<p>Left identity 跟 right identity 是描述 <code>return</code> 的行為。他重要的原因是因為他把普通值轉換成具有 context 的值，如果他出錯的話會很頭大。</p>
<a name="Associativity"></a><h3>Associativity</h3>


<p>單子律最後一條是說當我們用 <code>&gt;&gt;=</code> 把一串 monadic function 串在一起，他們的先後順序不應該影響結果：</p>

<p>  * <code>(m &gt;&gt;= f) &gt;&gt;= g</code> 跟 <code>m &gt;&gt;= (\x -&gt; f x &gt;&gt;= g)</code> 是相等的</p>

<p>究竟這邊說的是什麼呢？我們有一個 monadic value <code>m</code>，以及兩個 monadic function <code>f</code> 跟 <code>g</code>。當我們寫下 <code>(m &gt;&gt;= f) &gt;&gt;= g</code>，代表的是我們把 <code>m</code> 餵給 <code>f</code>，他的結果是一個 monadic value。然後我們把這個結果餵給 <code>g</code>。而在 <code>m &gt;&gt;= (\x -&gt; f x &gt;&gt;= g)</code> 中，我們接受一個 monadic value 然後餵給一個函數，這個函數會把 <code>f x</code> 的結果丟給 <code>g</code>。我們不太容易直接看出兩者相同，所以先來看個範例比較好理解。</p>

<p>還記得之前皮爾斯的範例嗎？要模擬鳥停在他的平衡竿上，我們把好幾個函數串在一起</p>
<pre class="code">ghci&gt; return (0,0) &gt;&gt;= landRight 2 &gt;&gt;= landLeft 2 &gt;&gt;= landRight 2  
Just (2,4)</pre>
<p>從 <code>Just (0,0)</code> 出發，然後把值傳給 <code>landRight 2</code>。他的結果又被綁到下一個 monadic function，以此類推。如果我們用括號清楚標出優先順序的話會是這樣：</p>
<pre class="code">ghci&gt; ((return (0,0) &gt;&gt;= landRight 2) &gt;&gt;= landLeft 2) &gt;&gt;= landRight 2  
Just (2,4)</pre>
<p>我們也可以改寫成這樣：</p>
<pre class="code">return (0,0) &gt;&gt;= (\x -&gt; 
landRight 2 x &gt;&gt;= (\y -&gt; 
landLeft 2 y &gt;&gt;= (\z -&gt; 
landRight 2 z)))</pre>
<p><code>return (0,0)</code> 等價於 <code>Just (0,0)</code>，當我們把他餵給 lambda，裡面的 <code>x</code> 就等於 <code>(0,0)</code>。<code>landRight</code> 接受一個數值跟 pole，算出來的結果是 <code>Just (0,2)</code> 然後把他餵給另一個 lambda，裡面的 <code>y</code> 就變成了 <code>(0,2)</code>。這樣的操作持續下去，直到最後一隻鳥降落，而得到 <code>Just (2,4)</code> 的結果，這也是整個操作的總結果。</p>

<p>這些 monadic function 的優先順序並不重要，重點是他們的意義。從另一個角度來看這個定律：考慮兩個函數 <code>f</code> 跟 <code>g</code>，將兩個函數組合起來的定義像是這樣：</p>
<pre class="code">(.) :: (b -&gt; c) -&gt; (a -&gt; b) -&gt; (a -&gt; c)  
f . g = (\x -&gt; f (g x))</pre>
<p>如果 <code>g</code> 的型態是 <code>a -&gt; b</code> 且 <code>f</code> 的型態是 <code>b -&gt; c</code>，我們可以把他們合成一個型態是 <code>a -&gt; c</code> 的新函數。所以中間的參數都有自動帶過。現在假設這兩個函數是 monadic function，也就是說如果他們的回傳值是 monadic function？如果我們有一個函數他的型態是 <code>a -&gt; m b</code>，我們並不能直接把結果丟給另一個型態為 <code>b -&gt; m c</code> 的函數，因為後者只接受型態為 <code>b</code> 的普通值。然而，我們可以用 <code>&gt;&gt;=</code> 來做到我們想要的事。有了 <code>&gt;&gt;=</code>，我們可以合成兩個 monadic function：</p>
<pre class="code">(&lt;=&lt;) :: (Monad m) =&gt; (b -&gt; m c) -&gt; (a -&gt; m b) -&gt; (a -&gt; m c)  
f &lt;=&lt; g = (\x -&gt; g x &gt;&gt;= f)</pre>
<p>所以現在我們可以合成兩個 monadic functions：</p>
<pre class="code">ghci&gt; let f x = [x,-x]  
ghci&gt; let g x = [x*3,x*2]  
ghci&gt; let h = f &lt;=&lt; g  
ghci&gt; h 3  
[9,-9,6,-6]</pre>
<p>至於這跟結合律有什麼關係呢？當我們把這定律看作是合成的定律，他就只是說了 <code>f &lt;=&lt; (g &lt;=&lt; h)</code> 跟 <code>(f &lt;=&lt; g) &lt;=&lt; h</code> 應該等價。只是他是針對 monad 而已。</p>

<p>如果我們把頭兩個單子律用 <code>&lt;=&lt;</code> 改寫，那 left identity 不過就是說對於每個 monadic function <code>f</code>，<code>f &lt;=&lt; return</code> 跟 <code>f</code> 是等價，而 right identity 說 <code>return &lt;=&lt; f</code> 跟 <code>f</code> 是等價。</p>

<p>如果看看普通函數的情形，就會發現很像，<code>(f . g) . h</code> 等價於 <code>f . (g . h)</code>，<code>f . id</code> 跟 <code>f</code> 等價，且 <code>id . f</code> 等價於 <code>f</code>。</p>

<p>在這一章中，我們檢視了 monad 的基本性質，而且也了解了 <code>Maybe</code> monad 跟 list monad 的運作方式。在下一章，我們會看看其他一些有特色的 monad，我們也會學到如何定義自己的 monad。</p>

            <ul class="nav">
                <li class="left">  <img src="../img/prv.png" alt="prev" /><a href="functors-applicative-functors-and-monoids.html">Functors, Applicative Functors 與 Monoids</a></li>
                <li class="center"><a href="chapters.html">目录</a></li>
                <li class="right"> <a href="for-a-few-monads-more.html">再來看看更多 Monad</a><img src="../img/nxt.png" alt="next" /></li>
            </ul>
        </div>
        <div id="footer">
        </div>
        <div id="feedback">Send feedback</div>
    </body>
</html>
